use crate::NetworkCommands;
use indicatif::{ProgressBar, ProgressStyle};
use reqwest;
use std::fs;
use std::path::Path;
use std::time::{Duration, Instant};
use tokio;

pub async fn handle_network_commands(command: NetworkCommands, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    match command {
        NetworkCommands::Ping { host, timeout, count } => {
            ping_host(&host, timeout, count, verbose).await?;
        },
        NetworkCommands::Download { url, output, threads } => {
            download_file(&url, output.as_deref(), threads, verbose).await?;
        },
        NetworkCommands::Upload { file, url, token } => {
            upload_file(&file, &url, token.as_deref(), verbose).await?;
        },
        NetworkCommands::Scan { target, ports, timeout } => {
            scan_ports(&target, &ports, timeout, verbose).await?;
        },
    }
    Ok(())
}

async fn ping_host(host: &str, timeout: u64, count: u32, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    println!("🏓 正在ping {} (超时: {}秒, 次数: {})", host, timeout, count);
    
    let client = reqwest::Client::builder()
        .timeout(Duration::from_secs(timeout))
        .build()?;
    
    let mut total_time = Duration::new(0, 0);
    let mut successful = 0;
    
    for i in 1..=count {
        let start = Instant::now();
        let url = if host.starts_with("http") {
            host.to_string()
        } else {
            format!("http://{}", host)
        };
        
        match client.get(&url).send().await {
            Ok(response) => {
                let duration = start.elapsed();
                total_time += duration;
                successful += 1;
                
                println!("来自 {} 的回复: 时间={}ms, 状态={}", 
                    host, duration.as_millis(), response.status());
            },
            Err(e) => {
                println!("请求 {} 失败: {}", i, e);
            }
        }
        
        if i < count {
            tokio::time::sleep(Duration::from_millis(500)).await;
        }
    }
    
    if successful > 0 {
        let avg_time = total_time / successful;
        println!("统计信息:");
        println!("  数据包: 已发送 = {}, 已接收 = {}, 丢失 = {} ({}% 丢失)", 
            count, successful, count - successful, 
            ((count - successful) as f64 / count as f64 * 100.0) as u32);
        println!("  往返行程的估计时间(以毫秒为单位):");
        println!("    最短 = {}ms, 最长 = {}ms, 平均 = {}ms", 
            total_time.as_millis() / successful as u128,
            total_time.as_millis() / successful as u128,
            avg_time.as_millis());
    }
    
    Ok(())
}

async fn download_file(url: &str, output: Option<&Path>, threads: usize, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    println!("⬇️  正在下载: {}", url);
    
    let client = reqwest::Client::new();
    let response = client.head(url).send().await?;
    
    if !response.status().is_success() {
        return Err(format!("HTTP 错误: {}", response.status()).into());
    }
    
    let content_length = response.headers()
        .get("content-length")
        .and_then(|h| h.to_str().ok())
        .and_then(|s| s.parse::<u64>().ok());
    
    let pb = if let Some(length) = content_length {
        ProgressBar::new(length)
    } else {
        ProgressBar::new_spinner()
    };
    
    pb.set_style(ProgressStyle::default_bar()
        .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} {msg}")?
        .progress_chars("#>-"));
    
    let response = client.get(url).send().await?;
    let mut stream = response.bytes_stream();
    let mut bytes = Vec::new();
    
    use futures_util::StreamExt;
    while let Some(chunk) = stream.next().await {
        let chunk = chunk?;
        bytes.extend_from_slice(&chunk);
        pb.inc(chunk.len() as u64);
        pb.set_message("下载中...");
    }
    
    let output_path = output.unwrap_or_else(|| Path::new("downloaded_file"));
    fs::write(output_path, bytes)?;
    
    pb.finish_with_message("✅ 下载完成");
    println!("📁 文件已保存到: {}", output_path.display());
    
    Ok(())
}

async fn upload_file(file: &Path, url: &str, token: Option<&str>, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    if !file.exists() {
        return Err("文件不存在".into());
    }
    
    println!("⬆️  正在上传: {} -> {}", file.display(), url);
    
    let client = reqwest::Client::new();
    let file_contents = fs::read(file)?;
    
    let mut request = client.post(url).body(file_contents);
    
    if let Some(token) = token {
        request = request.header("Authorization", format!("Bearer {}", token));
    }
    
    let response = request.send().await?;
    
    if response.status().is_success() {
        println!("✅ 上传成功");
        if verbose {
            println!("响应: {}", response.text().await?);
        }
    } else {
        println!("❌ 上传失败: {}", response.status());
    }
    
    Ok(())
}

async fn scan_ports(target: &str, ports: &str, timeout: u64, verbose: bool) -> Result<(), Box<dyn std::error::Error>> {
    println!("🔍 扫描端口: {} ({})", target, ports);
    
    let port_range = parse_port_range(ports)?;
    let mut open_ports = Vec::new();
    
    let pb = ProgressBar::new(port_range.len() as u64);
    pb.set_style(ProgressStyle::default_bar()
        .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} {msg}")?
        .progress_chars("#>-"));
    
    for port in port_range {
        pb.set_message(format!("扫描端口 {}", port));
        
        if let Ok(stream) = tokio::net::TcpStream::connect_timeout(
            &format!("{}:{}", target, port).parse()?,
            Duration::from_secs(timeout)
        ).await {
            open_ports.push(port);
            if verbose {
                println!("端口 {} 开放", port);
            }
        }
        
        pb.inc(1);
    }
    
    pb.finish_with_message("✅ 扫描完成");
    
    println!("扫描结果:");
    if open_ports.is_empty() {
        println!("  没有发现开放的端口");
    } else {
        println!("  开放端口: {:?}", open_ports);
    }
    
    Ok(())
}

fn parse_port_range(ports: &str) -> Result<Vec<u16>, Box<dyn std::error::Error>> {
    let mut result = Vec::new();
    
    for part in ports.split(',') {
        if part.contains('-') {
            let range: Vec<&str> = part.split('-').collect();
            if range.len() == 2 {
                let start: u16 = range[0].parse()?;
                let end: u16 = range[1].parse()?;
                for port in start..=end {
                    result.push(port);
                }
            }
        } else {
            result.push(part.parse()?);
        }
    }
    
    Ok(result)
}
